﻿//
//  Kursawe.cs
//
//  Author:
//       Antonio J. Nebro <antonio@lcc.uma.es>
//
//  Copyright (c) 2011 Antonio J. Nebro
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
// 
//  You should have received a copy of the GNU Lesser General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using jmetal.core;
using jmetal.encodings.variable;
using jmetal.encodings.solutionType;

namespace jmetal.problems
{
  public class Kursawe : Problem
  {
    public Kursawe (String solutionType) : this(solutionType, 3)
    {
    }

    public Kursawe (String solutionType, int numberOfVariables)
    {
      numberOfVariables_ = numberOfVariables;
      numberOfObjectives_ = 2;
      numberOfConstraints_ = 0;
      problemName_ = "Kursawe";
      
      lowerLimit_ = new double[numberOfVariables_];
      upperLimit_ = new double[numberOfVariables_];
      for (int i = 0; i < numberOfVariables_; i++)
      {
        lowerLimit_[i] = -5.0;
        upperLimit_[i] = 5.0;
      }
      
      if (solutionType == "Real")
        solutionType_ = new RealSolutionType (this);
    }

    public override void evaluate (Solution solution)
    {
      // <pex>
      if (solution == (Solution)null)
        throw new ArgumentNullException ("solution");
      if (solution.variable_ == (Variable[])null)
        throw new ArgumentNullException ("solution");
      // </pex>
      Variable[] x = solution.variable_;
      double[] fx = new double[numberOfObjectives_];
      double aux, xi, xj;

      fx[0] = 0.0;
      for (int var = 0; var < numberOfVariables_ - 1; var++) {
        xi = x[var].value_ * x[var].value_;
        xj = x[var + 1].value_ * x[var + 1].value_;
        aux = (-0.2) * Math.Sqrt (xi + xj);
        fx[0] += (-10.0) * Math.Exp (aux);
      }
      // for
      fx[1] = 0.0;
      
      for (int var = 0; var < numberOfVariables_; var++) {
        fx[1] += Math.Pow (Math.Abs (x[var].value_), 0.8) + 5.0 * Math.Sin (Math.Pow (x[var].value_, 3.0));
      }
      // for

      solution.objective_[0] = fx[0];
      solution.objective_[1] = fx[1];
    }
    // evaluate
  }
}
